﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ClassBuilder.Comment;

namespace ClassBuilder
{
    /// <summary>
    /// 
    /// </summary>
    public class CSClass
    {

        public HashSet<string> Pragmas = new HashSet<string>()
        {
            "#pragma warning disable IDE1006" //忽略警告（命名规则冲突：这些字必须以大写字母开头）
        };

        /// <summary>
        /// using的命名空间
        /// </summary>
        public HashSet<string> UsingNameSpaces { get; set; } = new HashSet<string>()
        {
            "System",
            "System.Collections.Generic",
            "System.Linq",
            "System.Text"
        };

        /// <summary>
        /// 命名空间
        /// </summary>
        public string NameSpace { get; set; }


        /// <summary>
        /// 类名称
        /// </summary>
        public string ClassName { get; set; }


        /// <summary>
        /// 全名称
        /// </summary>
        public string FullName { get { return NameSpace + "." + ClassName; } }


        /// <summary>
        /// 命名规则
        /// </summary>
        public NameRule NameRule { get; set; } = NameRule.Normal;

        /// <summary>
        /// 类注释
        /// </summary>
        public CSComment Comment { get; set; }


        /// <summary>
        /// 是否有命名空间
        /// </summary>
        private bool IsHaveNS { get; set; }

        /// <summary>
        /// 存储临时数据
        /// </summary>
        public object Tag { get; set; }

        /// <summary>
        /// 所有类属性信息
        /// </summary>
        public List<CSPropInfo> All_Prop { get; set; } = new List<CSPropInfo>();


        public CSClass(string className, string nameSpace = null, CSComment comment = null, NameRule nameRule = NameRule.Normal)
        {
            this.ClassName = className?.NameStyle(nameRule);
            this.NameSpace = nameSpace?.NameStyle(nameRule);
            this.IsHaveNS = !string.IsNullOrWhiteSpace(this.NameSpace);
            this.Comment = comment;
            this.NameRule = nameRule;
        }

        public void AddUsingNameSpace(string nameSpace)
        {
            if (nameSpace.NotEmpty())
            {
                UsingNameSpaces.Add(nameSpace);
            }
        }

        public void AddProperty(CSPropInfo propInfo)
        {
            All_Prop.Add(propInfo);
        }

        public void AddProperty(Type propType, string propName, object defaultValue = null, CSComment comment = null)
        {
            var prop = new CSPropInfo(propType, propName?.NameStyle(this.NameRule), defaultValue, comment);
            AddProperty(prop);
        }

        public void AddProperty(string propClassName, string propName, object defaultValue = null, CSComment comment = null, bool isEnumType = false)
        {
            var prop = new CSPropInfo(propClassName, propName?.NameStyle(this.NameRule), defaultValue, comment, isEnumType);
            AddProperty(prop);
        }

        public void AddProperty(string propName, object defaultValue = null, CSComment comment = null)
        {
            var prop = new CSPropInfo(propName?.NameStyle(this.NameRule), defaultValue, comment);
            AddProperty(prop);
        }



        /// <summary>
        /// 该类的唯一Id
        /// </summary>
        public string Id
        {
            get
            {
                var strs = All_Prop.Select(t => t.PropTypeName + t.Name?.NameStyle(this.NameRule) + t.DefaultValue).ToArray();
                Array.Sort(strs);
                return string.Join(ClassName, strs).Md5();
            }
        }

        /// <summary>
        /// 对象包含属性值的唯一Id
        /// </summary>
        public string MId
        {
            get
            {
                var strs = All_Prop.Select(t => t.PropTypeName + t.Name?.NameStyle(this.NameRule)).ToArray();
                Array.Sort(strs);
                return string.Join("", strs).Md5();
            }
        }

        public string Value
        {
            get
            {
                if (string.IsNullOrWhiteSpace(this.ClassName))
                {
                    return string.Empty;
                }

                StringPlus Plus = new StringPlus();

                if (Pragmas.Count > 0)
                {
                    foreach (var pragma in Pragmas)
                    {
                        Plus.AppendLine($"{pragma.Trim()}");
                    }
                }


                if (UsingNameSpaces.Count > 0)
                {
                    foreach (var space in UsingNameSpaces)
                    {
                        Plus.AppendLine($"using {space.Trim()};");
                    }
                }

                Plus.AppendLine();

                if (!string.IsNullOrWhiteSpace(NameSpace))
                {
                    Plus.AppendLine($"namespace {NameSpace}");
                    Plus.AppendLine("{");
                }

                if (Comment != null && !string.IsNullOrWhiteSpace(Comment.Value))
                {
                    if (!IsHaveNS)
                    {
                        Plus.Append(Comment.Value);
                    }
                    else
                    {
                        var lines = Comment.Value.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var line in lines)
                        {
                            Plus.AppendSpaceLine(1, line);
                        }
                    }
                }

                Plus.AppendSpaceLine(IsHaveNS ? 1 : 0, $"public class {this.ClassName}");
                Plus.AppendSpaceLine(IsHaveNS ? 1 : 0, "{");
                Plus.AppendLine();

                var lenSpace = (string.IsNullOrWhiteSpace(NameSpace) ? 0 : 1) + 1;

                for (int j = 0; j < All_Prop.Count; j++)
                {
                    var propInfo = All_Prop[j];

                    foreach (var line in propInfo.Lines)
                    {
                        Plus.AppendSpaceLine(lenSpace, line);
                    }

                    if (j != All_Prop.Count - 1)
                    {
                        Plus.AppendLine();
                    }
                }

                Plus.AppendLine();
                Plus.AppendSpaceLine(IsHaveNS ? 1 : 0, "}");

                if (IsHaveNS)
                {
                    Plus.AppendLine("}");
                }
                return Plus.ToString().Trim();
            }
        }
    }
}
